/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
** 
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
** 
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
** Lesser General Public License for more details.
** 
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/


//============================================================================
/// \file   DockWidget.cpp
/// \author Uwe Kindler
/// \date   26.02.2017
/// \brief  Implementation of CDockWidget class
//============================================================================


//============================================================================
//                                   INCLUDES
//============================================================================
#include <AutoHideDockContainer.h>
#include <AutoHideSideBar.h>
#include <AutoHideTab.h>
#include "DockWidgetTab.h"
#include "DockWidget.h"

#include <iostream>

#include <QBoxLayout>
#include <QAction>
#include <QSplitter>
#include <QStack>
#include <QScrollArea>
#include <QTextStream>
#include <QPointer>
#include <QEvent>
#include <QDebug>
#include <QToolBar>
#include <QXmlStreamWriter>
#include <QWindow>

#include <QGuiApplication>
#include <QScreen>
#include <QWindow>

#include "DockContainerWidget.h"
#include "DockAreaWidget.h"
#include "DockManager.h"
#include "FloatingDockContainer.h"
#include "DockSplitter.h"
#include "DockComponentsFactory.h"
#include "ads_globals.h"


namespace ads
{
/**
 * CDockWidget类的私有数据类（pimpl）
 */
struct DockWidgetPrivate
{
    struct WidgetFactory
    {
        CDockWidget::FactoryFunc createWidget;
        CDockWidget::eInsertMode insertMode;
    };

    CDockWidget* _this = nullptr;
    QBoxLayout* Layout = nullptr;
    QWidget* Widget = nullptr;
    CDockWidgetTab* TabWidget = nullptr;
    CDockWidget::DockWidgetFeatures Features = CDockWidget::DefaultDockWidgetFeatures;
    CDockManager* DockManager = nullptr;
    CDockAreaWidget* DockArea = nullptr;
    QAction* ToggleViewAction = nullptr;
    bool Closed = false;
    QScrollArea* ScrollArea = nullptr;
    QToolBar* ToolBar = nullptr;
    Qt::ToolButtonStyle ToolBarStyleDocked = Qt::ToolButtonIconOnly;
    Qt::ToolButtonStyle ToolBarStyleFloating = Qt::ToolButtonTextUnderIcon;
    QSize ToolBarIconSizeDocked = QSize(16, 16);
    QSize ToolBarIconSizeFloating = QSize(24, 24);
    bool IsFloatingTopLevel = false;
    QList<QAction*> TitleBarActions;
    CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
    WidgetFactory* Factory = nullptr;
    QPointer<CAutoHideTab> SideTabWidget;

    /**
     * 私有数据构造函数
     */
    DockWidgetPrivate(CDockWidget* _public);

    /**
     * 显示停靠窗口
     */
    void showDockWidget();

    /**
     * 隐藏停靠窗口。
     */
    void hideDockWidget();

    /**
     * 如果区域中的所有停靠窗口都关闭，则隐藏停靠区域。
     * 此函数更新当前选中的选项卡，并在区域为空时隐藏父停靠区域。
     */
    void updateParentDockArea();

    /**
     * 如果没有打开的停靠区域，则关闭所有自动隐藏的停靠窗口。
     * 这样可以防止自动隐藏的停靠窗口固定在空的停靠区域上。
     */
    void closeAutoHideDockWidgetsIfNeeded();

    /**
     * 设置顶部工具栏
     */
    void setupToolBar();

    /**
     * 设置主滚动区域
     */
    void setupScrollArea();

    /**
     * 使用注册的小部件工厂创建内容小部件，并在成功时返回true。
     */
    bool createWidgetFromFactory();
};
// struct DockWidgetPrivate

//============================================================================
// DockWidgetPrivate 构造函数
DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
    _this(_public)
{
}

//============================================================================
// 显示 Dock Widget 的方法
void DockWidgetPrivate::showDockWidget()
{
    // 如果 Widget 尚未创建
    if (!Widget)
    {
        // 尝试从工厂创建 Widget
        if (!createWidgetFromFactory())
        {
            // 如果设置了 DeleteContentOnClose 标志，但是 Widget 工厂缺失或者不返回有效的 QWidget，则断言并返回
            Q_ASSERT(!Features.testFlag(CDockWidget::DeleteContentOnClose) &&
                     "DeleteContentOnClose 标志已设置，但 Widget 工厂缺失或不返回有效的 QWidget。");
            return;
        }
    }

    // 如果 Dock 区域未设置
    if (!DockArea)
    {
        // 创建一个新的浮动 Dock 容器
        CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
        // 使用内容 Widget 的大小提示来提供一个良好的初始大小
        FloatingWidget->resize(Widget ? Widget->sizeHint() : _this->sizeHint());
        // 显示选项卡部件
        TabWidget->show();
        // 显示浮动部件
        FloatingWidget->show();
    }
    else
    {
        // 设置 Dock 区域的当前 Dock Widget
        DockArea->setCurrentDockWidget(_this);
        // 切换 Dock 区域的视图
        DockArea->toggleView(true);
        // 显示选项卡部件
        TabWidget->show();
        // 查找父级分割器并显示，如果它不可见且 Dock 区域不是自动隐藏的
        QSplitter* Splitter = internal::findParent<QSplitter*>(DockArea);
        while (Splitter && !Splitter->isVisible() && !DockArea->isAutoHide())
        {
            Splitter->show();
            Splitter = internal::findParent<QSplitter*>(Splitter);
        }
        // 获取 Dock 区域的 Dock 容器
        CDockContainerWidget* Container = DockArea->dockContainer();
        // 如果容器是浮动的，则显示浮动部件
        if (Container->isFloating())
        {
            CFloatingDockContainer* FloatingWidget = internal::findParent<
                    CFloatingDockContainer*>(Container);
            FloatingWidget->show();
        }

        // 如果此 Widget 是固定的且没有打开的 Dock Widget，则通过将其内容移动到父容器来取消固定自动隐藏的 Widget
        // 在恢复状态时，打开的 Dock Widget 无效
        if (Container->openedDockWidgets().count() == 0 && DockArea->isAutoHide() && !DockManager->isRestoringState())
        {
            DockArea->autoHideDockContainer()->moveContentsToParent();
        }
    }
}

//============================================================================
// 隐藏 Dock Widget 的方法
void DockWidgetPrivate::hideDockWidget()
{
    // 隐藏选项卡部件
    TabWidget->hide();
    // 更新父 Dock 区域
    updateParentDockArea();
    // 如有需要，关闭自动隐藏的 Dock Widget
    closeAutoHideDockWidgetsIfNeeded();
    // 如果设置了 DeleteContentOnClose 标志，稍后删除 Widget
    if (Features.testFlag(CDockWidget::DeleteContentOnClose))
    {
        Widget->deleteLater();
        Widget = nullptr;
    }
}


//============================================================================
// 更新父Dock区域
void DockWidgetPrivate::updateParentDockArea()
{
    if (!DockArea)
    {
        return;
    }
    
    // 如果当前的Dock窗口不是即将关闭的窗口，则不需要改变当前选项卡
    if (DockArea->currentDockWidget() != _this){
        return;
    }
    
    auto NextDockWidget = DockArea->nextOpenDockWidget(_this);
    
    if (NextDockWidget)
    {
        DockArea->setCurrentDockWidget(NextDockWidget);
    }
    else
    {
        DockArea->hideAreaWithNoVisibleContent();
    }
}
//============================================================================
// 如果需要，关闭自动隐藏的Dock窗口
void DockWidgetPrivate::closeAutoHideDockWidgetsIfNeeded()
{
    auto DockContainer = _this->dockContainer();
    
    if (!DockContainer)
    {
        return;
    }
    
    if (_this->dockManager()->isRestoringState())
    {
        return;
    }
    
    if (!DockContainer->openedDockWidgets().isEmpty())
    {
        return;
    }
    
    for (auto autoHideWidget : DockContainer->autoHideWidgets())
    {
        auto DockWidget = autoHideWidget->dockWidget();
        
        if (DockWidget == _this)
        {
            continue;
        }
        
        DockWidget->toggleView(false);
    }
}
//============================================================================
// 设置工具栏
void DockWidgetPrivate::setupToolBar()
{
    ToolBar = new QToolBar(_this);
    ToolBar->setObjectName("dockWidgetToolBar");
    Layout->insertWidget(0, ToolBar);
    ToolBar->setIconSize(QSize(16, 16));
    ToolBar->toggleViewAction()->setEnabled(false);
    ToolBar->toggleViewAction()->setVisible(false);
    _this->connect(_this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
}
//============================================================================
// 设置滚动区域
void DockWidgetPrivate::setupScrollArea()
{
    ScrollArea = new QScrollArea(_this);
    ScrollArea->setObjectName("dockWidgetScrollArea");
    ScrollArea->setWidgetResizable(true);
    Layout->addWidget(ScrollArea);
}
//============================================================================
// 从工厂创建窗口部件
bool DockWidgetPrivate::createWidgetFromFactory()
{
    if (!Features.testFlag(CDockWidget::DeleteContentOnClose))
    {
        return false;
    }
    
    if (!Factory)
    {
        return false;
    }
    
    QWidget* w = Factory->createWidget(_this);
    
    if (!w)
    {
        return false;
    }
    
    _this->setWidget(w, Factory->insertMode);
    return true;
}


// CDockWidget类的构造函数
CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
	QFrame(parent),
	d(new DockWidgetPrivate(this))
{
	// 创建一个QBoxLayout，设置其方向为从上到下
	d->Layout = new QBoxLayout(QBoxLayout::TopToBottom);
	// 设置QBoxLayout的边距为0
	d->Layout->setContentsMargins(0, 0, 0, 0);
	// 设置QBoxLayout的间距为0
	d->Layout->setSpacing(0);
	// 将QBoxLayout设置为CDockWidget的布局
	setLayout(d->Layout);
	// 设置CDockWidget的窗口标题
	setWindowTitle(title);
	// 设置CDockWidget的对象名称
	setObjectName(title);
	// 创建一个QTabWidget，用于管理CDockWidget
	d->TabWidget = componentsFactory()->createDockWidgetTab(this);
	// 创建一个QAction，用于切换CDockWidget的显示状态
	d->ToggleViewAction = new QAction(title, this);
	// 将QAction设置为可选中状态
	d->ToggleViewAction->setCheckable(true);
	// 连接QAction的信号和CDockWidget的槽函数
	connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
		SLOT(toggleView(bool)));
	// 设置CDockWidget的工具栏浮动样式
	setToolbarFloatingStyle(false);
	// 如果CDockManager的FocusHighlighting标志被设置
	if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
	{
		// 设置CDockWidget的焦点策略为单击获得焦点
		setFocusPolicy(Qt::ClickFocus);
	}
}

// CDockWidget类的析构函数
CDockWidget::~CDockWidget()
{
	// 打印日志
	ADS_PRINT("~CDockWidget()");
	// 删除CDockWidget的私有数据
	delete d;
}

// 设置CDockWidget的切换显示状态的QAction是否被选中
void CDockWidget::setToggleViewActionChecked(bool Checked)
{
	// 获取CDockWidget的切换显示状态的QAction
	QAction* Action = d->ToggleViewAction;
	// 阻止QAction的信号
	Action->blockSignals(true);
	// 设置QAction的选中状态
	Action->setChecked(Checked);
	// 恢复QAction的信号
	Action->blockSignals(false);
}

// 设置CDockWidget的子部件
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
{
	// 如果CDockWidget已经有子部件了
	if (d->Widget)
	{
		// 移除CDockWidget的子部件
		takeWidget();
	}
	// 如果widget是QAbstractScrollArea或者InsertMode是ForceNoScrollArea
	auto ScrollAreaWidget = qobject_cast<QAbstractScrollArea*>(widget);
	if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
	{
		// 将widget添加到CDockWidget的布局中
		d->Layout->addWidget(widget);
		// 如果widget是QAbstractScrollArea并且其viewport存在
		if (ScrollAreaWidget && ScrollAreaWidget->viewport())
		{
			// 将viewport的属性设置为dockWidgetContent
			ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
		}
	}
	else
	{
		// 设置CDockWidget的滚动区域
		d->setupScrollArea();
		// 将widget设置为CDockWidget的滚动区域的子部件
		d->ScrollArea->setWidget(widget);
	}
	// 设置CDockWidget的子部件
	d->Widget = widget;
	// 将CDockWidget的子部件的属性设置为dockWidgetContent
	d->Widget->setProperty("dockWidgetContent", true);
}

//============================================================================
// 设置小部件工厂
void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode)
{
    // 如果已经存在工厂对象，则删除它
    if (d->Factory)
    {
        delete d->Factory;
    }
    // 创建新的工厂对象
    d->Factory = new DockWidgetPrivate::WidgetFactory { createWidget, insertMode };
}
//============================================================================
// 获取小部件并移除
QWidget* CDockWidget::takeWidget()
{
    QWidget* w = nullptr;
    // 如果存在滚动区域，则从布局中移除并获取小部件
    if (d->ScrollArea)
    {
        d->Layout->removeWidget(d->ScrollArea);
        w = d->ScrollArea->takeWidget();
        delete d->ScrollArea;
        d->ScrollArea = nullptr;
        d->Widget = nullptr;
    }
    // 否则，如果存在小部件，则从布局中移除
    else if (d->Widget)
    {
        d->Layout->removeWidget(d->Widget);
        w = d->Widget;
        d->Widget = nullptr;
    }
    // 如果获取到小部件，则将其父对象设置为nullptr
    if (w)
    {
        w->setParent(nullptr);
    }
    return w;
}
//============================================================================
// 获取小部件
QWidget* CDockWidget::widget() const
{
    return d->Widget;
}
//============================================================================
// 获取选项卡小部件
CDockWidgetTab* CDockWidget::tabWidget() const
{
    return d->TabWidget;
}
//============================================================================
// 获取自动隐藏的停靠容器
CAutoHideDockContainer* CDockWidget::autoHideDockContainer() const
{
    if (!d->DockArea)
    {
        return nullptr;
    }
    return d->DockArea->autoHideDockContainer();
}
//============================================================================
// 设置小部件的特性
void CDockWidget::setFeatures(DockWidgetFeatures features)
{
    // 如果特性没有变化，则直接返回
    if (d->Features == features)
    {
        return;
    }
    d->Features = features;
    // 发送特性变化的信号
    Q_EMIT featuresChanged(d->Features);
    // 更新选项卡小部件的特性
    d->TabWidget->onDockWidgetFeaturesChanged();
    // 如果存在停靠区域小部件，则更新其特性
    if (CDockAreaWidget* DockArea = dockAreaWidget())
        DockArea->onDockWidgetFeaturesChanged();
}
//============================================================================
// 设置特定特性的状态
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
{
    auto Features = features();
    // 根据指定的状态设置特性
    internal::setFlag(Features, flag, on);
    setFeatures(Features);
}
//============================================================================
// 获取小部件的特性
CDockWidget::DockWidgetFeatures CDockWidget::features() const
{
    return d->Features;
}


//============================================================================
// 获取dockManager
CDockManager* CDockWidget::dockManager() const
{
	return d->DockManager;
}
//============================================================================
// 设置dockManager
void CDockWidget::setDockManager(CDockManager* DockManager)
{
	d->DockManager = DockManager;
}
//============================================================================
// 获取dockContainer
CDockContainerWidget* CDockWidget::dockContainer() const
{
	if (d->DockArea)
	{
		return d->DockArea->dockContainer();
	}
	else
	{
		return nullptr;
	}
}
//============================================================================
// 获取floatingDockContainer
CFloatingDockContainer* CDockWidget::floatingDockContainer() const
{
	auto DockContainer = dockContainer();
	return DockContainer ? DockContainer->floatingWidget() : nullptr;
}
//============================================================================
// 获取dockAreaWidget
CDockAreaWidget* CDockWidget::dockAreaWidget() const
{
	return d->DockArea;
}
//============================================================================
// 获取sideTabWidget
CAutoHideTab* CDockWidget::sideTabWidget() const
{
	return d->SideTabWidget;
}
//============================================================================
// 设置sideTabWidget
void CDockWidget::setSideTabWidget(CAutoHideTab* SideTab)
{
	d->SideTabWidget = SideTab;
}
//============================================================================
// 判断是否为自动隐藏
bool CDockWidget::isAutoHide() const
{
	return !d->SideTabWidget.isNull();
}
//============================================================================
// 获取自动隐藏位置
SideBarLocation CDockWidget::autoHideLocation() const
{
	return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
}
//============================================================================
// 判断是否为浮动状态
bool CDockWidget::isFloating() const
{
	if (!isInFloatingContainer())
	{
		return false;
	}
	return dockContainer()->topLevelDockWidget() == this;
}
//============================================================================
// 判断是否在浮动容器中
bool CDockWidget::isInFloatingContainer() const
{
	auto Container = dockContainer();
	if (!Container)
	{
		return false;
	}
	if (!Container->isFloating())
	{
		return false;
	}
	return true;
}


//============================================================================
// 判断Dock Widget是否关闭
bool CDockWidget::isClosed() const
{
    return d->Closed;
}

//============================================================================
// 获取切换视图的动作
QAction* CDockWidget::toggleViewAction() const
{
    return d->ToggleViewAction;
}

//============================================================================
// 设置切换视图的动作模式
void CDockWidget::setToggleViewActionMode(eToggleViewActionMode Mode)
{
    if (ActionModeToggle == Mode)
    {
        // 如果模式为切换，则将动作设置为可选中，并移除图标
        d->ToggleViewAction->setCheckable(true);
        d->ToggleViewAction->setIcon(QIcon());
    }
    else
    {
        // 如果模式不是切换，则将动作设置为不可选中，并设置图标为选项卡小部件的图标
        d->ToggleViewAction->setCheckable(false);
        d->ToggleViewAction->setIcon(d->TabWidget->icon());
    }
}

//============================================================================
// 设置最小大小提示模式
void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
{
    d->MinimumSizeHintMode = Mode;
}

//============================================================================
// 获取最小大小提示模式
CDockWidget::eMinimumSizeHintMode CDockWidget::minimumSizeHintMode() const
{
    return d->MinimumSizeHintMode;
}

//============================================================================
// 判断是否为中央部件
bool CDockWidget::isCentralWidget() const
{
    return dockManager()->centralWidget() == this;
}

//============================================================================
// 切换Dock Widget的显示状态
void CDockWidget::toggleView(bool Open)
{
    // 如果切换视图动作模式为ActionModeShow，并且触发信号的发送者是切换视图动作，则始终将Open设置为true
    QAction* Sender = qobject_cast<QAction*>(sender());
    if (Sender == d->ToggleViewAction && !d->ToggleViewAction->isCheckable())
    {
        Open = true;
    }

    // 如果Dock Widget的状态不同，则需要切换状态。
    // 如果Dock Widget处于正确的状态，则将其设置为当前Dock Widget
    auto AutoHideContainer = autoHideDockContainer();
    if (d->Closed != !Open)
    {
        toggleViewInternal(Open);
    }
    else if (Open && d->DockArea && !AutoHideContainer)
    {
        raise();
    }

    if (Open && AutoHideContainer)
    {
        AutoHideContainer->collapseView(false);
    }
}


//============================================================================
// 切换视图的内部函数，根据 "Open" 参数切换 Dock Widget 的视图
void CDockWidget::toggleViewInternal(bool Open)
{
    // 获取 Dock Container
    CDockContainerWidget* DockContainer = dockContainer();
    
    // 在切换视图之前获取顶层 Dock Widget
    CDockWidget* TopLevelDockWidgetBefore = DockContainer ? DockContainer->topLevelDockWidget() : nullptr;
    
    // 根据 "Open" 参数更新关闭状态
    d->Closed = !Open;
    
    // 根据 "Open" 参数显示或隐藏 Dock Widget
    if (Open)
    {
        d->showDockWidget();
    }
    else
    {
        d->hideDockWidget();
    }
    
    // 阻塞切换视图动作的信号
    d->ToggleViewAction->blockSignals(true);
    
    // 设置切换视图动作的选中状态
    d->ToggleViewAction->setChecked(Open);
    
    // 解除阻塞切换视图动作的信号
    d->ToggleViewAction->blockSignals(false);
    
    // 在 Dock Area 中切换 Dock Widget 的视图
    if (d->DockArea)
    {
        d->DockArea->toggleDockWidgetView(this, Open);
    }
    
    // 在自动隐藏的 Dock Container 中切换视图
    if (d->DockArea->isAutoHide())
    {
        d->DockArea->autoHideDockContainer()->toggleView(Open);
    }
    
    // 在切换视图之前发出顶层 Dock Widget 的事件
    if (Open && TopLevelDockWidgetBefore)
    {
        CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetBefore, false);
    }
    
    // 再次获取 Dock Container，以防在调用 showDockWidget() 之前它被取消分配
    DockContainer = dockContainer();
    
    // 在切换视图之后获取顶层 Dock Widget
    CDockWidget* TopLevelDockWidgetAfter = DockContainer ? DockContainer->topLevelDockWidget() : nullptr;
    
    // 发出切换视图之后顶层 Dock Widget 的事件
    CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true);
    
    // 获取浮动的 Dock Container
    CFloatingDockContainer* FloatingContainer = DockContainer ? DockContainer->floatingWidget() : nullptr;
    
    // 更新浮动的 Dock Container 的窗口标题
    if (FloatingContainer)
    {
        FloatingContainer->updateWindowTitle();
    }
    
    // 如果 Dock Widget 被关闭，则发出 closed 信号
    if (!Open)
    {
        Q_EMIT closed();
    }
    
    // 发出 viewToggled 信号
    Q_EMIT viewToggled(Open);
}
//============================================================================
// 设置 Dock Widget 的 Dock Area
void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
{
    // 设置 Dock Area
    d->DockArea = DockArea;
    
    // 根据 Dock Area 和关闭状态设置切换视图动作的选中状态
    d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed());
    
    // 将父对象设置为 Dock Area
    setParent(DockArea);
}
//============================================================================

// 该函数保存了dock widget的状态 
void CDockWidget::saveState(QXmlStreamWriter& s) const 
{ 
    // 写入widget的开始元素 
    s.writeStartElement("Widget"); 
    // 写入name属性 
    s.writeAttribute("Name", objectName()); 
    // 写入closed属性 
    s.writeAttribute("Closed", QString::number(d->Closed ? 1 : 0)); 
    // 写入widget的结束元素 
    s.writeEndElement(); 
} 
 
//============================================================================ 
 
// 该函数将dock widget标记为未分配 
void CDockWidget::flagAsUnassigned() 
{ 
    // 将closed状态设置为true 
    d->Closed = true; 
    // 将parent设置为dock manager 
    setParent(d->DockManager); 
    // 将可见性设置为false 
    setVisible(false); 
    // 将dock area设置为nullptr 
    setDockArea(nullptr); 
    // 将tab widget的parent设置为this 
    tabWidget()->setParent(this); 
} 
 
//============================================================================ 
 
// 该函数处理dock widget的事件 
bool CDockWidget::event(QEvent *e) 
{ 
    switch (e->type()) 
    { 
        case QEvent::Hide: 
            // 当dock widget隐藏时发射visibilityChanged信号 
            Q_EMIT visibilityChanged(false); 
            break; 
        case QEvent::Show: 
            // 当dock widget显示时发射visibilityChanged信号 
            Q_EMIT visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0); 
            break; 
        case QEvent::WindowTitleChange: 
            { 
                // 使用窗口标题更新tab widget、side tab widget和toggle view action的文本 
                const auto title = windowTitle(); 
                if (d->TabWidget) 
                { 
                    d->TabWidget->setText(title); 
                } 
                if (d->SideTabWidget) 
                { 
                    d->SideTabWidget->setText(title); 
                } 
                if (d->ToggleViewAction) 
                { 
                    d->ToggleViewAction->setText(title); 
                } 
                // 标记标题栏菜单为过时，以更新tabs菜单 
                if (d->DockArea) 
                { 
                    d->DockArea->markTitleBarMenuOutdated(); 
                } 
                // 更新浮动dock容器的窗口标题 
                auto FloatingWidget = floatingDockContainer(); 
                if (FloatingWidget) 
                { 
                    FloatingWidget->updateWindowTitle(); 
                } 
                // 发射titleChanged信号 
                Q_EMIT titleChanged(title); 
            } 
            break; 
        default: 
            break; 
    } 
    // 调用基类的event函数 
    return Super::event(e); 
} 


#ifndef QT_NO_TOOLTIP

// 设置标签的工具提示文本
void CDockWidget::setTabToolTip(const QString &text)
{
    if (d->TabWidget)
    {
        d->TabWidget->setToolTip(text);
    }
    if (d->ToggleViewAction)
    {
        d->ToggleViewAction->setToolTip(text);
    }
    if (d->DockArea)
    {
        d->DockArea->markTitleBarMenuOutdated(); // 更新标签菜单
    }
}

#endif

// 设置图标
void CDockWidget::setIcon(const QIcon& Icon)
{
    d->TabWidget->setIcon(Icon);
    if (d->SideTabWidget)
    {
        d->SideTabWidget->setIcon(Icon);
    }
    if (!d->ToggleViewAction->isCheckable())
    {
        d->ToggleViewAction->setIcon(Icon);
    }
}

// 获取图标
QIcon CDockWidget::icon() const
{
    return d->TabWidget->icon();
}

// 获取工具栏
QToolBar* CDockWidget::toolBar() const
{
    return d->ToolBar;
}

// 创建默认的工具栏
QToolBar* CDockWidget::createDefaultToolBar()
{
    if (!d->ToolBar)
    {
        d->setupToolBar();
    }
    return d->ToolBar;
}

// 设置工具栏
void CDockWidget::setToolBar(QToolBar* ToolBar)
{
    if (d->ToolBar)
    {
        delete d->ToolBar;
    }
    d->ToolBar = ToolBar;
    d->Layout->insertWidget(0, d->ToolBar);
    this->connect(this, SIGNAL(topLevelChanged(bool)), SLOT(setToolbarFloatingStyle(bool)));
    setToolbarFloatingStyle(isFloating());
}

// 设置工具栏样式
void CDockWidget::setToolBarStyle(Qt::ToolButtonStyle Style, eState State)
{
    if (StateFloating == State)
    {
        d->ToolBarStyleFloating = Style;
    }
    else
    {
        d->ToolBarStyleDocked = Style;
    }
    setToolbarFloatingStyle(isFloating());
}

// 获取工具栏样式
Qt::ToolButtonStyle CDockWidget::toolBarStyle(eState State) const
{
    if (StateFloating == State)
    {
        return d->ToolBarStyleFloating;
    }
    else
    {
        return d->ToolBarStyleDocked;
    }
}


//============================================================================
// 设置工具栏图标大小
void CDockWidget::setToolBarIconSize(const QSize& IconSize, eState State)
{
    if (StateFloating == State)
    {
        d->ToolBarIconSizeFloating = IconSize;
    }
    else
    {
        d->ToolBarIconSizeDocked = IconSize;
    }
    setToolbarFloatingStyle(isFloating());
}
//============================================================================
// 获取工具栏图标大小
QSize CDockWidget::toolBarIconSize(eState State) const
{
    if (StateFloating == State)
    {
        return d->ToolBarIconSizeFloating;
    }
    else
    {
        return d->ToolBarIconSizeDocked;
    }
}
//============================================================================
// 设置工具栏浮动样式
void CDockWidget::setToolbarFloatingStyle(bool Floating)
{
    if (!d->ToolBar)
    {
        return;
    }
    auto IconSize = Floating ? d->ToolBarIconSizeFloating : d->ToolBarIconSizeDocked;
    if (IconSize != d->ToolBar->iconSize())
    {
        d->ToolBar->setIconSize(IconSize);
    }
    auto ButtonStyle = Floating ? d->ToolBarStyleFloating : d->ToolBarStyleDocked;
    if (ButtonStyle != d->ToolBar->toolButtonStyle())
    {
        d->ToolBar->setToolButtonStyle(ButtonStyle);
    }
}
//============================================================================
// 发送顶层事件给小部件
void CDockWidget::emitTopLevelEventForWidget(CDockWidget* TopLevelDockWidget, bool Floating)
{
    if (TopLevelDockWidget)
    {
        TopLevelDockWidget->dockAreaWidget()->updateTitleBarVisibility();
        TopLevelDockWidget->emitTopLevelChanged(Floating);
    }
}
//============================================================================
// 发送顶层改变事件
void CDockWidget::emitTopLevelChanged(bool Floating)
{
    if (Floating != d->IsFloatingTopLevel)
    {
        d->IsFloatingTopLevel = Floating;
        Q_EMIT topLevelChanged(d->IsFloatingTopLevel);
    }
}
//============================================================================
// 设置关闭状态
void CDockWidget::setClosedState(bool Closed)
{
    d->Closed = Closed;
}
//============================================================================
// 获取最小尺寸提示
QSize CDockWidget::minimumSizeHint() const
{
    if (!d->Widget)
    {
        return QSize(60, 40);
    }
    switch (d->MinimumSizeHintMode)
    {
        case MinimumSizeHintFromDockWidget: return QSize(60, 40);
        case MinimumSizeHintFromContent: return d->Widget->minimumSizeHint();
        case MinimumSizeHintFromDockWidgetMinimumSize: return minimumSize();
        case MinimumSizeHintFromContentMinimumSize: return d->Widget->minimumSize();
    }
    return d->Widget->minimumSizeHint();
}


//============================================================================
// 设置Dock Widget为浮动状态
void CDockWidget::setFloating()
{
    // 如果Dock Widget已关闭，则返回
    if (isClosed())
    {
        return;
    }

    // 如果Dock Widget设置为自动隐藏，则将Dock Area设置为浮动状态
    if (this->isAutoHide())
    {
        dockAreaWidget()->setFloating();
    }
    else
    {
        // 从标签小部件中分离出Dock Widget
        d->TabWidget->detachDockWidget();
    }
}
//============================================================================
// 删除Dock Widget
void CDockWidget::deleteDockWidget()
{
    auto manager = dockManager();
    if (manager)
    {
        // 从Dock Manager中移除Dock Widget
        manager->removeDockWidget(this);
    }
    // 延迟删除Dock Widget
    deleteLater();
    d->Closed = true;
}
//============================================================================
// 关闭Dock Widget
void CDockWidget::closeDockWidget()
{
    closeDockWidgetInternal(true);
}
//============================================================================
// 请求关闭Dock Widget
void CDockWidget::requestCloseDockWidget()
{
    // 如果Dock Widget具有DockWidgetDeleteOnClose或CustomCloseHandling特性，则在内部关闭Dock Widget。否则，切换Dock Widget的视图。
    if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose)
        || features().testFlag(CDockWidget::CustomCloseHandling))
    {
        closeDockWidgetInternal(false);
    }
    else
    {
        toggleView(false);
    }
}
//============================================================================
// 内部关闭Dock Widget
bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
{
    // 如果ForceClose为false，则发射closeRequested信号
    if (!ForceClose)
    {
        Q_EMIT closeRequested();
    }

    // 如果ForceClose为false并且Dock Widget具有CustomCloseHandling特性，则返回false
    if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
    {
        return false;
    }

    // 如果Dock Widget具有DockWidgetDeleteOnClose特性
    if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
    {
        // 如果Dock Widget是浮动的
        if (isFloating())
        {
            // 查找父级浮动Dock容器
            CFloatingDockContainer* FloatingWidget = internal::findParent<CFloatingDockContainer*>(this);

            // 如果浮动容器中只有一个Dock Widget，则删除浮动容器
            if (FloatingWidget->dockWidgets().count() == 1)
            {
                FloatingWidget->deleteLater();
            }
            else
            {
                FloatingWidget->hide();
            }
        }

        // 如果Dock Widget的Dock Area设置为自动隐藏，则清理并删除自动隐藏的Dock容器
        if (d->DockArea && d->DockArea->isAutoHide())
        {
            d->DockArea->autoHideDockContainer()->cleanupAndDelete();
        }

        // 删除Dock Widget
        deleteDockWidget();

        // 发射closed信号
        Q_EMIT closed();
    }
    else
    {
        // 切换Dock Widget的视图
        toggleView(false);
    }

    return true;
}


//============================================================================

// 设置标题栏动作
void CDockWidget::setTitleBarActions(QList<QAction*> actions)
{
    d->TitleBarActions = actions;
}

//============================================================================

// 返回标题栏动作列表
QList<QAction*> CDockWidget::titleBarActions() const
{
    return d->TitleBarActions;
}

//============================================================================

// 全屏显示
void CDockWidget::showFullScreen()
{
    if (isFloating())
    {
        dockContainer()->floatingWidget()->showFullScreen();
    }
    else
    {
        Super::showFullScreen();
    }
}

//============================================================================

// 恢复正常显示
void CDockWidget::showNormal()
{
    if (isFloating())
    {
        dockContainer()->floatingWidget()->showNormal();
    }
    else
    {
        Super::showNormal();
    }
}

//============================================================================

// 是否全屏显示
bool CDockWidget::isFullScreen() const
{
    if (isFloating())
    {
        return dockContainer()->floatingWidget()->isFullScreen();
    }
    else
    {
        return Super::isFullScreen();
    }
}

//============================================================================

// 将当前标签设为活动标签
void CDockWidget::setAsCurrentTab()
{
    if (d->DockArea && !isClosed())
    {
        d->DockArea->setCurrentDockWidget(this);
    }
}

//============================================================================

// 是否为标签页式显示
bool CDockWidget::isTabbed() const
{
    return d->DockArea && (d->DockArea->openDockWidgetsCount() > 1);
}

//============================================================================

// 是否为当前活动标签
bool CDockWidget::isCurrentTab() const
{
    return d->DockArea && (d->DockArea->currentDockWidget() == this);
}

//============================================================================

// 提升窗口
void CDockWidget::raise()
{
    if (isClosed())
    {
        return;
    }
    setAsCurrentTab();
    if (isInFloatingContainer())
    {
        auto FloatingWindow = window();
        FloatingWindow->raise();
        FloatingWindow->activateWindow();
    }
}


//============================================================================

// 设置自动隐藏功能
void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex)
{
    // 如果自动隐藏功能未启用，则不做任何操作
    if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
    {
        return;
    }
    
    // 如果没有任何改变，则不做任何操作
    if (Enable == isAutoHide() && Location == autoHideLocation())
    {
        return;
    }
    
    auto DockArea = dockAreaWidget();
    
    if (!Enable)
    {
        // 关闭自动隐藏
        DockArea->setAutoHide(false);
    }
    else if (isAutoHide())
    {
        // 移动到新的侧边栏位置
        autoHideDockContainer()->moveToNewSideBarLocation(Location);
    }
    else
    {
        auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location;
        
        // 创建并设置自动隐藏容器
        dockContainer()->createAndSetupAutoHideContainer(area, this, TabIndex);
    }
}

//============================================================================

// 切换自动隐藏状态
void CDockWidget::toggleAutoHide(SideBarLocation Location)
{
    // 如果自动隐藏功能未启用，则不做任何操作
    if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled))
    {
        return;
    }
    
    // 切换自动隐藏状态
    setAutoHide(!isAutoHide(), Location);
}

} // namespace ads

//---------------------------------------------------------------------------
// EOF DockWidget.cpp
